package com.yiboshi.rehrs.util;

import cn.hutool.core.lang.Pair;
import com.yiboshi.rehrs.exception.ZyantExceptionUtils;
import com.yiboshi.rehrs.util.js.CipherPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.ExceptionUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Base64;
@Slf4j
public class AesGcmUtil {

    private static final String ALGORITHM = "AES/GCM/NoPadding";
    private static final int GCM_TAG_LENGTH_BITS = 128; // 128-bit authentication tag
    private static final int GCM_IV_LENGTH_BYTES = 12;  // 96-bit IV (recommended)

    static {
        Security.addProvider(new BouncyCastleProvider());
    }



    static byte[] keyBytes = "!384Application@".getBytes();
    public static String encryptAccount( String token){
        try {
            String encrypt = encrypt(keyBytes, token );
            return encrypt;
        }catch (Exception e){
            log.error("",e);
            ZyantExceptionUtils.e(true,"账号加密失败");
        }
        return null;
    }

    public static Pair<String,String> decryptAccount(String encryptText) {
        try {
            String key = "account:" + encryptText;
            Pair byCache10Min = CacheUtils.getByCache10Min(key, Pair.class);
            if (byCache10Min!=null){
                return byCache10Min;
            }
            String encrypt = decrypt(keyBytes, encryptText);
            Pair<String, String> stringStringPair = null;
            if(!encrypt.contains(":")){
                stringStringPair =  Pair.of(encrypt,"");//token:账号
            }else{
                String[] split = encrypt.split(":");
                stringStringPair = Pair.of(split[0], split[1]);//token：账号

            }
            CacheUtils.putByCache10Min(key, stringStringPair);
            return stringStringPair;
        }catch (Exception e){
            log.error("",e);
        }
        return null;

    }



    /**
     * AES/GCM 加密
     *
     * @param keyBytes 16字节的AES密钥（128位）
     * @param plaintext 明文
     * @return Base64编码的密文（包含IV）
     * @throws Exception
     */
    public static String encrypt(byte[] keyBytes, String plaintext) throws Exception { // 移除了 ivBytes 参数
        Cipher cipher = null;
        try {
            cipher = CipherPool.borrowCipher(ALGORITHM);
            SecretKey key = new SecretKeySpec(keyBytes, "AES");

            // 生成随机IV
            byte[] ivBytes = new byte[GCM_IV_LENGTH_BYTES];
            new SecureRandom().nextBytes(ivBytes); // 使用安全随机数生成器

            GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH_BITS, ivBytes);
            cipher.init(Cipher.ENCRYPT_MODE, key, spec);

            byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8"));

            // 合并 IV + 密文
            byte[] ivAndCiphertext = new byte[ivBytes.length + ciphertext.length];
            System.arraycopy(ivBytes, 0, ivAndCiphertext, 0, ivBytes.length);
            System.arraycopy(ciphertext, 0, ivAndCiphertext, ivBytes.length, ciphertext.length);

            return Base64.getEncoder().encodeToString(ivAndCiphertext);
        } finally {
            CipherPool.returnCipher(cipher, ALGORITHM);
        }
    }

    /**
     * AES/GCM 解密
     *
     * @param keyBytes 16字节的AES密钥（128位）
     * @param encryptedData Base64编码的密文（包含IV）
     * @return 明文字符串
     * @throws Exception
     */
    public static String decrypt(byte[] keyBytes, String encryptedData) throws Exception {
        Cipher cipher = null;
        try {
            byte[] data = Base64.getDecoder().decode(encryptedData);

            // 提取 IV
            byte[] ivBytes = new byte[GCM_IV_LENGTH_BYTES];
            System.arraycopy(data, 0, ivBytes, 0, GCM_IV_LENGTH_BYTES);

            cipher = CipherPool.borrowCipher(ALGORITHM);

            SecretKey key = new SecretKeySpec(keyBytes, "AES");
            GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH_BITS, ivBytes);
            cipher.init(Cipher.DECRYPT_MODE, key, spec);

            // 提取密文
            byte[] ciphertext = new byte[data.length - GCM_IV_LENGTH_BYTES];
            System.arraycopy(data, GCM_IV_LENGTH_BYTES, ciphertext, 0, ciphertext.length);

            byte[] plaintext = cipher.doFinal(ciphertext);
            return new String(plaintext, "UTF-8");
        } finally {
            CipherPool.returnCipher(cipher, ALGORITHM);
        }
    }


    // 测试用例
    // mUSsoL+PES8MsipM5eb3j+RHSQjIXkFZpNGYF3Lq5vI6OVrCTWPa6KA=
    //xTohdKplsEg16k6crHVwG8L9lShuUftcHpbqGvK6+xH9NZ54eiYWqKL00iAKL7OS4SNNjytMiP1P8/lUaN12/qu4JVwbUTRP8GI=
    public static void main(String[] args) throws Exception {
        String plainText = "2153011500166+6e31e00a04b44ff1890531c1ed94b573";
        byte[] key = "1234567890abcdef".getBytes("UTF-8"); // 16字节的密钥
        byte[] iv = "1234567890ab".getBytes("UTF-8");      // 12字节的IV

        String encrypted = encrypt(key, plainText);
        System.out.println("Encrypted: " + encrypted);

        String decrypted = decrypt(key, encrypted);
        System.out.println("Decrypted: " + decrypted);


        encrypted = encrypt(key, plainText);
        System.out.println("Encrypted: " + encrypted);

        decrypted = decrypt(key, encrypted);
        System.out.println("Decrypted: " + decrypted);
    }
}
